using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

using MegaEngine.Source.Tiles;
using MegaEngine.Source.Sprites;
using MegaEngine.Source.GameData.Tetris;

namespace MegaEngine.Source.Levels
{
    class Tetris : MegaEngineGame
    {
        int fallingSpeed;
        int levelUp;
        int maxFallingSpeed = 500;
        int lines;
        int level;
        TetrisPiece current;
        TetrisPiece next;
        TetrisPiece displayNext;
        long setTimer = 0;

        Sprite[,] gameBoard;
        ArrayList screen = new ArrayList();
        public Tetris()
        {   
            tilePaths = new String[2];
            spritePaths = new String[1];
            tileTextures = new Texture2D[2];
            spriteTextures = new Texture2D[1];
            tilePaths[0] = "Content\\Textures\\Tiles\\Black";
            tilePaths[1] = "Content\\Textures\\Tiles\\Black";
            spritePaths[0] = "Content\\Textures\\Sprites\\Tetris\\tetrisbrick";
            xBounds = 30;
            yBounds = 21;
        }
        
        public override void update(GameTime gameTime)
        {
            buildEnvironment();
            if (current.update(spriteOrigin.X, -256f, xBounds * 32, yBounds * 32, gameTime, environment, spriteOrigin) == 1)
            {
                setTimer += gameTime.ElapsedGameTime.Milliseconds;
                if(setTimer>=150){
                    setTimer = 0;
                    setTetrisPiece();
                    current = next;
                    current.setSpritePositions();
                    next = new TetrisPiece(spriteTextures[0], fallingSpeed);
                    setDisplayNext();
                    buildEnvironment();
                }
            }
            foreach (Sprite s in current.getSprites())
            {
                environment.Add(s);
            }
        }
        private void buildEnvironment()
        {
            environment.Clear();
            foreach (Sprite s in screen)
            {
                environment.Add(s);
            }
            foreach (Sprite s in gameBoard)
            {
                if (s != null)
                {
                    environment.Add(s);
                }
            }
            displayNext.setSpritePositions();
            foreach (Sprite s in displayNext.getSprites())
            {
                environment.Add(s);
            }
        }
        private void loadEnvironment()
        {
            screen = TetrisLevelLoader.getEnvironment("Content\\Levels\\Tetris\\TetrisBoard", spriteTextures);
        }
        private void setTetrisPiece()
        {
            ArrayList sprites = current.getSprites();
            try
            {
                foreach (Sprite s in sprites)
                {
                    int gameBoardXPosition = ((int)s.levelOrigin.X >> 5) - 8;
                    int gameBoardYPosition = ((int)s.levelOrigin.Y >> 5);
                    Console.WriteLine("X:" + gameBoardXPosition + " Y:" + gameBoardYPosition);
                    s.levelOrigin.X = (gameBoardXPosition + 8) << 5;
                    s.levelOrigin.Y = gameBoardYPosition << 5;
                    gameBoard[gameBoardXPosition, gameBoardYPosition] = s;
                }
                clearLines();
            }
            catch (Exception)
            {
                init(); // restart the game if an exception occurs trying to place a piece in an invalid location
            }
        }

        private void clearLines()
        {
            for (int y = 0; y < 20; y++)
            {
                int rowCount = 0;
                for (int x = 0; x < 10; x++)
                {
                    if (gameBoard[x, y] != null)
                    {
                        rowCount++;
                    }
                }
                if (rowCount == 10)
                {
                    lines++;
                    if (lines >= levelUp)
                    {
                        level++;
                        levelUp += 10;
                        fallingSpeed = fallingSpeed >= maxFallingSpeed ? fallingSpeed : fallingSpeed + 25;
                    }
                    clearRow(y);
                }
            }
        }

        private void clearRow(int row)
        {
            for (int y = row-1; y > 0; y--)
            {
                for (int x = 0; x < 10; x++)
                {
                    if (gameBoard[x, y] != null)
                    {
                        gameBoard[x, y].levelOrigin.Y+=32;
                    }
                    gameBoard[x, y + 1] = gameBoard[x, y];
                }
            }
        }
        public override void init()
        {
            lines = 0;
            level = 0;
            levelUp = 10;
            fallingSpeed = 50;
            npcs = new ArrayList();
            environment = new ArrayList();
            backgroundLayer3 = new Texture2D[xBounds, yBounds];
            for (int i = 0; i < xBounds; i++)
            {
                for (int j = 0; j < yBounds; j++)
                {
                    if (i % 2 == 0 && j % 2 == 0 || i % 2 == 1 && j % 2 == 1)
                    {
                        backgroundLayer3[i, j] = tileTextures[0];
                    }
                    else
                    {
                        backgroundLayer3[i, j] = tileTextures[1];
                    }
                }
            }
            viewFrame = new Tile[26, 20];
            for (int i = 0; i < 26; i++)
            {
                for (int j = 0; j < 20; j++)
                {
                    viewFrame[i, j] = new Tile();
                }
            }
            current = new TetrisPiece(spriteTextures[0], fallingSpeed);
            next = new TetrisPiece(spriteTextures[0], fallingSpeed);
            setDisplayNext();
            loadEnvironment();
            gameBoard = new Sprite[10, 20];
            environment = new ArrayList();
        }
        private void setDisplayNext()
        {
            displayNext = new TetrisPiece(spriteTextures[0], fallingSpeed, next.pieceId);
            displayNext.initializePiece();
            displayNext.setDisplayNext();
        }
        public override void renderHud(MegaEngine.Source.Font.XNAFont fontRenderer, bool showFPS, GameTime gameTime)
        {
            fontRenderer.OutputText("NEXT: ", 640, 0, Color.White);
            fontRenderer.OutputText("Lines: ", 640, 256, Color.White);
            fontRenderer.OutputText(lines.ToString(), 640, 288, Color.White);
            fontRenderer.OutputText("Level: ", 640, 320, Color.White);
            fontRenderer.OutputText(level.ToString(), 640, 352, Color.White);
            fontRenderer.OutputText("Speed: ", 640, 384, Color.White);
            fontRenderer.OutputText(fallingSpeed.ToString(), 640, 416, Color.White);
            base.renderHud(fontRenderer, showFPS, gameTime);
        }
    }
}
